/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.core.sql.result;

import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by walle on 12/9/15.
 */
public class DataResult {
    private static final Logger log = LoggerFactory.getLogger(DataResult.class);
    private long runtime;
    private static final long serialVersionUID = 1L;
    private int pageSize = 10;
    private int currentPage;
    private int totalSize;
    private int totalPage;
    private List<Map<String, Object>> resultList;
    private List<List<Object>> resultListArray;
    private java.util.Date ctime;
    private List<String> titles;
    private String message;
    private String sortTitleText;
    private String sortTypeText;
    private int startPage;
    private int endPage;

    public static DataResult getInstance() {
        return getInstance(new ArrayList(), 0, 1, 0);
    }

    public static DataResult getInstance(List<Map<String, Object>> data, int _totalSize, int _currentPage, int _PageSize) {
        DataResult result = new DataResult();
        result.resultList = data;
        result.totalSize = _totalSize;
        result.currentPage = _currentPage;
        result.pageSize = _PageSize;
        if (result.totalSize == 0) {
            result.totalPage = 0;
            result.startPage = 0;
            result.endPage = 0;
            return result;
        }
        result.totalPage = (result.totalSize / result.pageSize + 1);
        if (result.totalSize % result.pageSize == 0) {
            result.totalPage -= 1;
        }

        result.startPage = (result.currentPage - 2);

        result.endPage = (result.currentPage + 2);
        if (result.startPage < 1) {
            int cha = 1 - result.startPage;
            result.startPage = 1;
            result.endPage += cha;
        }
        if (result.endPage > result.totalPage) {
            result.endPage = result.totalPage;
        }
        return result;
    }

    public void LoadListArray() {
        this.resultListArray = new ArrayList();
        for (Map node : getResultList()) {
            List list = new ArrayList();
            for (String key : this.titles) {
                list.add(node.get(key));
            }
            this.resultListArray.add(list);
        }
    }

    public DataResult mergeCells(String titleKey) {
        String key = titleKey + "ROWSPAN";
        for (int i = 0; i < this.resultList.size(); i++) {
            Object cellsVal = ((Map) this.resultList.get(i)).get(titleKey);
            Object rowspan = ((Map) this.resultList.get(i)).get(key);
            if (rowspan == null) {
                int rowspanNum = 0;
                for (int n = i; n < this.resultList.size(); n++) {
                    Object tempVal = ((Map) this.resultList.get(n)).get(titleKey);
                    if ((tempVal == null) || (!tempVal.equals(cellsVal))) break;
                    rowspanNum++;
                    ((Map) this.resultList.get(i)).put(key, Integer.valueOf(0));
                }

                ((Map) this.resultList.get(i)).put(key, Integer.valueOf(rowspanNum));
            }

        }

        return this;
    }

    public void LoadListArray(String titless) {
        this.resultListArray = new ArrayList();
        for (Map node : getResultList()) {
            List list = new ArrayList();
            for (String key : DataResults.getTitles(titless)) {
                list.add(node.get(key));
            }
            this.resultListArray.add(list);
        }
    }

    public static DataResult setMessager(DataResult dataResult, String messager) {
        if (dataResult == null) {
            dataResult = new DataResult();
            dataResult.resultList = new ArrayList();
        }
        dataResult.setMessage(messager);
        return dataResult;
    }

    public void printDataInfo() {
        System.out.println("############       debug开始         #############################################################");

        DataResults.printMaps(getResultList());
        System.out.println("当前页:" + getCurrentPage());
        System.out.println("全部页:" + gettotalPage());
        System.out.println("全部记录:" + getTotalSize());
        System.out.println("每页数:" + getPageSize());
        System.out.println("消息:" + this.message);
        System.out.println("############       debug结束         #############################################################");
    }

    public DataResult runDictionary(Map<String, String> dictionary, String title) {
        for (Map node : this.resultList) {
            String key = String.valueOf(node.get(title));
            Object value = dictionary.get(key);
            if (value != null) {
                node.put(title, value);
            }
        }
        return this;
    }

    public DataResult runDictionary(String str, String title) {
        String[] mapStr = str.trim().split(",");
        Map dictionary = new HashMap();
        for (String keyValue : mapStr) {
            String[] node = keyValue.split(":");
            try {
                dictionary.put(node[0], node[1]);
            } catch (Exception e) {
                throw new RuntimeException(e + ",请检查字典项：'" + keyValue + "'");
            }
        }
        runDictionary(dictionary, title);
        return this;
    }

    public void runformatTime(String title, String yyyyMMddHHmmss) {
        List<Map<String, Object>> list = getResultList();
        for (Map node : list)
            try {
                String time = null;
                if ((node.get(title) instanceof java.sql.Date)) {
                    java.util.Date d = new java.util.Date(((java.sql.Date) node.get(title)).getTime());
                    SimpleDateFormat ormat = new SimpleDateFormat("yyyyMMdd");
                    time = ormat.format(d);
                } else {
                    time = (String) node.get(title);
                }
                if ((time == null) || (time.trim().length() > 0)) {
                    if (12 == time.length()) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
                        SimpleDateFormat newSdf = new SimpleDateFormat(yyyyMMddHHmmss);
                        java.util.Date date = sdf.parse(time);
                        node.put(title, newSdf.format(date));
                    } else {
                        try {
                            time = (time + "00000000000000").substring(0, 14);
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                            SimpleDateFormat newSdf = new SimpleDateFormat(yyyyMMddHHmmss);
                            java.util.Date date = sdf.parse(time);
                            node.put(title, newSdf.format(date));
                        } catch (ParseException e) {
                            node.put(title, null);
                        }
                    }
                }
            } catch (Exception e) {
                log.warn("", e);
            }

    }

    public DataResult removeDataResult(DataResult result, String mapTitle) {
        Set keyset = new HashSet();

        for (Map node : result.getResultList()) {
            keyset.add((String) node.get(mapTitle));
        }
        List<Map> temp = new ArrayList();
        for (Map node : this.resultList) {
            String key = (String) node.get(mapTitle);
            if ((key != null) && (!"".equals(key)) &&
                    (!keyset.add(key))) {
                temp.add(node);
                this.totalSize -= 1;
            }
        }

        for (Map node : temp) {
            this.resultList.remove(node);
        }
        return result;
    }

    public DataResult runDistinct(String title) {
        List<Map<String, Object>> list = getResultList();
        List listresult = new ArrayList();
        Set keySet = new HashSet();
        for (Map node : list) {
            String key = node.get(title).toString();
            if (keySet.add(key)) {
                listresult.add(node);
            }
        }
        setResultList(listresult);
        return this;
    }

    public int getPageSize() {
        return this.pageSize;
    }

    public int getCurrentPage() {
        return this.currentPage;
    }

    public int gettotalPage() {
        return this.totalPage;
    }

    public List<Map<String, Object>> getResultList() {
        return this.resultList;
    }

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setResultList(List<Map<String, Object>> resultList) {
        this.resultList = resultList;
    }

    public void addTitle(String titel, String value) {
        for (Map node : this.resultList)
            node.put(titel, value);
    }

    public List<List<Object>> getResultListArray() {
        return this.resultListArray;
    }

    public void setResultListArray(List<List<Object>> resultListArray) {
        this.resultListArray = resultListArray;
    }

    public int getTotalSize() {
        return this.totalSize;
    }

    public int getTotalPage() {
        return this.totalPage;
    }

    public List<String> getTitles() {
        return this.titles;
    }

    public void setTitles(List<String> titles) {
        this.titles = titles;
    }

    public String getSortTitleText() {
        return this.sortTitleText;
    }

    public void setSortTitleText(String sortTitleText) {
        this.sortTitleText = sortTitleText;
    }

    public java.util.Date getCtime() {
        return this.ctime;
    }

    public void setCtime(java.util.Date ctime) {
        this.ctime = ctime;
    }

    public String getSortTypeText() {
        return this.sortTypeText;
    }

    public void setSortTypeText(String sortTypeText) {
        this.sortTypeText = sortTypeText;
    }

    public <T> List<T> getObjectList(Class class1) {
        List list = new ArrayList();
        for (Map<String, Object> node : getResultList()) {
            Object obj = null;
            try {
                obj = class1.newInstance();

                for (Map.Entry field : node.entrySet())
                    BeanUtils.setProperty(obj, ((String) field.getKey()).toLowerCase(), field.getValue());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            list.add(obj);
        }
        return list;
    }

    public int getStartPage() {
        return this.startPage;
    }

    public void setStartPage(int startPage) {
        this.startPage = startPage;
    }

    public int getEndPage() {
        return this.endPage;
    }

    public void setEndPage(int endPage) {
        this.endPage = endPage;
    }

    public long getRuntime() {
        return this.runtime;
    }

    public void setRuntime(long runtime) {
        this.runtime = runtime;
    }

    public void runHandle(ResultsHandle handle) {
        for (Map row : getResultList())
            handle.handle(row);
    }
}
